const { networkInterfaces } = require('os');
const {machineIdSync} = require('node-machine-id');
const os = require('os');
const md5 = require('md5');

function SystemUtils(){}

const virtualMacPrefix = new Set([
    '00:05:69', // vmware1
    '00:0c:29', // vmware2
    '00:50:56', // vmware3
    '00:1c:14', // vmware
    '00:1c:42', // parallels1
    '02:00:4c', // Microsoft Loopback Adapter (微软回环网卡)
    '00:03:ff', // microsoft virtual pc
    '00:0f:4b', // virtual iron 4
    '00:16:3e', // red hat xen , oracle vm , xen source, novell xen
    '08:00:27', // virtualbox
]);

function _isZeroMac(mac) {
    return /^(0{1,2}[:-]){5}0{1,2}$/.test(mac);
}

function _isMac(mac) {
    return /^([da-f]{1,2}[:-]){5}([da-f]{1,2})$/i.test(mac);
}

function _formatMac(mac) {
    return String(mac).trim().toLowerCase().replace(/-/g, ':');
}

function _isVirtualMac(mac) {
    return _isMac(mac) && virtualMacPrefix.has(_formatMac(mac).slice(0, 8));
}

/**
 * sort by: !internal > !zeroMac(mac) > visual > family=IPv4
 */
function _ifacesSort(list) {
    return list.sort((a, b) => {
        if (a.internal !== b.internal) return a.internal ? 1 : -1;
        if (_isZeroMac(a.mac) !== _isZeroMac(b.mac)) return _isZeroMac(a.mac) ? 1 : -1;
        const isVirtualA = _isVirtualMac(a.mac);
        const isVirtualB = _isVirtualMac(b.mac);
        if (isVirtualA !== isVirtualB) return isVirtualA ? 1 : -1;
        if (a.family !== b.family) return a.family === 'IPv6' ? 1 : -1;
    });
}

/**
 * 获取mac地址 - 排除 0 Mac
 * @returns {*[]}
 */
function getMac() {
    let nif = networkInterfaces();
    let all = [];
    for (let list of Object.values(nif)) {
        all = all.concat(list);
    }
    let nt = _ifacesSort(all)
    let macs = []
    for(let i of nt){
        if(!_isZeroMac(i.mac)){
            macs.push(i.mac)
        }
    }
    macs = Array.from(new Set(macs))
    return macs
}

/**
 * 获取设备ID
 * @returns {Promise<void>}
 */
function getMachineId() {
    let id = machineIdSync();
    return id;
}

/**
 * 获取cpu id
 */
function getCPUMD5(){
    let cpus = os.cpus();
    return md5(cpus)
}

if (typeof SystemUtils !== 'undefined') {
    SystemUtils.getMac = getMac
    SystemUtils.getMachineId = getMachineId;
    SystemUtils.getCPUMD5 = getCPUMD5;
}

module.exports = SystemUtils